package top.codedance.iotp.tools.terminal.ui;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import top.codedance.iotp.common.util.SystemUtil;
import top.codedance.iotp.tools.terminal.TerminalApplication;
import top.codedance.iotp.tools.terminal.comer.ComClient;
import top.codedance.iotp.tools.terminal.wser.WsClient;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author xuedianfu
 */
public class ConnectionManager extends javax.swing.JDialog {
    
    private ShellFrame sf;
    private AddConnection ac = null;
    public static final String CONNECTION_TMP_FILENAME = "terminal_connections";
    private JSONObject connectData = new JSONObject();
    private DefaultListModel dlmB;

    /**
     * Creates new form ConnectionManager
     */
    public ConnectionManager(ShellFrame sf) {
        super(sf, true);
        this.sf = sf;
        initComponents();
        URL url = Thread.currentThread().getContextClassLoader().getResource("logo.gif");
        ImageIcon icon = new ImageIcon(url);
        setIconImage(icon.getImage());
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        setMinimumSize(new Dimension(685, 500));
        setResizable(true);
        setTitle("代码飞舞采控系统-系统控制终端");
        initList();
    }

    public ShellFrame getShellFrame(){
        return this.sf;
    }

    public JSONObject getSelected(){
        if(!this.jl_connections.isSelectionEmpty()) {
            return connectData.getJSONObject(this.jl_connections.getSelectedValue());
        }else{
            return null;
        }
    }

    public void addSave(JSONObject jo){
        connectData.put(jo.getString("name"), jo);
        SystemUtil.genTempFile(CONNECTION_TMP_FILENAME, connectData.toJSONString());
        initListData();
        ac.cleanData();
        ac.setVisible(false);
    }

    public void initList(){
        dlmB = new DefaultListModel();
        this.jl_connections.setModel(dlmB);
        initListData();
    }

    public void initListData(){
        String s = SystemUtil.readTempFile(CONNECTION_TMP_FILENAME);
        if(null != s && !s.isEmpty()) {
            connectData = JSON.parseObject(s);
            dlmB.clear();
            Set<Map.Entry<String, Object>> entries = connectData.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                dlmB.addElement(entry.getKey());
            }
            this.jl_connections.repaint();
        }
    }

    public JSONObject getCurrentConnection(){
        JSONObject jsonObject = sf.exportConnectSetting();
        return jsonObject;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jl_connections = new javax.swing.JList<>();
        jb_add = new javax.swing.JButton();
        jb_toCurrent = new javax.swing.JButton();
        jb_del = new javax.swing.JButton();
        jb_load = new javax.swing.JButton();
        jb_export = new javax.swing.JButton();
        jb_diconnectAll = new javax.swing.JButton();
        jb_diconnect_selected = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setAlwaysOnTop(true);
        setMaximumSize(new java.awt.Dimension(600, 400));
        setMinimumSize(new java.awt.Dimension(600, 400));
        setResizable(false);
        setSize(new java.awt.Dimension(600, 400));

        jl_connections.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jl_connectionsMouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jl_connectionsMousePressed(evt);
            }
        });
        jScrollPane1.setViewportView(jl_connections);

        jb_add.setText("新增/编辑");
        jb_add.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_addActionPerformed(evt);
            }
        });

        jb_toCurrent.setText("设为当前");
        jb_toCurrent.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_toCurrentActionPerformed(evt);
            }
        });

        jb_del.setText("删除");
        jb_del.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_delActionPerformed(evt);
            }
        });

        jb_load.setText("导入连接");
        jb_load.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_loadActionPerformed(evt);
            }
        });

        jb_export.setText("导出连接");
        jb_export.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_exportActionPerformed(evt);
            }
        });

        jb_diconnectAll.setText("断开所有连接");
        jb_diconnectAll.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_diconnectAllActionPerformed(evt);
            }
        });

        jb_diconnect_selected.setText("断开选中连接");
        jb_diconnect_selected.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_diconnect_selectedActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jb_diconnectAll)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jb_diconnect_selected)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jb_export)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jb_load)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jb_toCurrent)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jb_add)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jb_del)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jb_add)
                    .addComponent(jb_toCurrent)
                    .addComponent(jb_del)
                    .addComponent(jb_load)
                    .addComponent(jb_export)
                    .addComponent(jb_diconnectAll)
                    .addComponent(jb_diconnect_selected))
                .addGap(11, 11, 11))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jb_addActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_addActionPerformed
        if(ac != null)
            ac.dispose();
        ac = new AddConnection(this);
        ac.setLocationRelativeTo(this);
        ac.setVisible(true);
    }//GEN-LAST:event_jb_addActionPerformed

    private void jb_toCurrentActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_toCurrentActionPerformed
        if(!this.jl_connections.isSelectionEmpty()) {
            JSONObject jsonObject = connectData.getJSONObject(this.jl_connections.getSelectedValue());
            this.sf.loadConnnectSetting(jsonObject);
            setVisible(false);
            sf.toFront();
        }else{
            JOptionPane.showMessageDialog(rootPane, "请选取一个连接配置");
        }
    }//GEN-LAST:event_jb_toCurrentActionPerformed

    private void jb_delActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_delActionPerformed
        if(!this.jl_connections.isSelectionEmpty()) {
            this.connectData.remove(this.jl_connections.getSelectedValue());
            SystemUtil.genTempFile(CONNECTION_TMP_FILENAME, connectData.toJSONString());
            initListData();
        }else{
            JOptionPane.showMessageDialog(rootPane, "请选取一个连接配置");
        }
    }//GEN-LAST:event_jb_delActionPerformed

    private void jl_connectionsMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jl_connectionsMousePressed
        if (this.jl_connections.locationToIndex(evt.getPoint()) == -1){
            this.jl_connections.clearSelection();
        }
    }//GEN-LAST:event_jl_connectionsMousePressed

    private void jb_loadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_loadActionPerformed
        JFileChooser jfc = new JFileChooser();
        jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        jfc.setFileFilter(new FileFilter() {
            @Override
            public boolean accept(File f) {
                if (f.isDirectory())
                    return true;
                return f.getName().endsWith(".txt");
            }
            @Override
            public String getDescription(){
                return ".txt";
            }
        });
        int i = jfc.showOpenDialog(this);
        if(i == JFileChooser.APPROVE_OPTION){
            File selectedFile = jfc.getSelectedFile();
            if(selectedFile.exists() && selectedFile.isFile()) {
                String s = SystemUtil.readFile(selectedFile);
                connectData = JSON.parseObject(s);
                SystemUtil.genTempFile(CONNECTION_TMP_FILENAME, connectData.toJSONString());
                initListData();
                JOptionPane.showMessageDialog(this.getRootPane(), "导入成功");
            }else{
                JOptionPane.showMessageDialog(this.getRootPane(), "请选取一个命令文本文件");
            }
        }
    }//GEN-LAST:event_jb_loadActionPerformed

    private void jb_exportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_exportActionPerformed
        JFileChooser jfc = new JFileChooser();
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int i = jfc.showOpenDialog(this);
        if(i == JFileChooser.APPROVE_OPTION) {
            File selectedFile = jfc.getSelectedFile();
            if(selectedFile.exists() && selectedFile.isDirectory()) {
                String data = connectData.toJSONString();
                String fileName = "terminal_connections.txt";
                String filepath = selectedFile.getAbsolutePath() + File.separatorChar + fileName;
                File f = new File(filepath);
                if(!f.exists()){
                    try {
                        f.createNewFile();
                    } catch (IOException e) {
                        TerminalApplication.syslogInfo(e.getMessage());
                        JOptionPane.showMessageDialog(this.getRootPane(), "创建文件失败，请确保当前用户对所选目录有可写权限");
                    }
                }
                SystemUtil.writeFile(filepath, data);
                JOptionPane.showMessageDialog(this.getRootPane(), "导出成功,文件是所选目录下的 " + fileName);
            }else{
                JOptionPane.showMessageDialog(this.getRootPane(), "请选取一个文件夹");
            }
        }
    }//GEN-LAST:event_jb_exportActionPerformed

    private void jb_diconnectAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_diconnectAllActionPerformed
        if(this.sf.ccs.size() > 0){
            Set<Map.Entry<String, ComClient>> entries = this.sf.ccs.entrySet();
            for (Map.Entry<String, ComClient> entry : entries){
                entry.getValue().close();
            }
            this.sf.ccs.clear();
        }
        if(this.sf.wcs.size() > 0){
            Set<Map.Entry<String, WsClient>> entries = this.sf.wcs.entrySet();
            for (Map.Entry<String, WsClient> entry : entries){
                entry.getValue().close();
            }
            this.sf.wcs.clear();
        }
        JOptionPane.showMessageDialog(this.getRootPane(), "操作成功");
    }//GEN-LAST:event_jb_diconnectAllActionPerformed

    private void jb_diconnect_selectedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_diconnect_selectedActionPerformed
        List<String> list = this.jl_connections.getSelectedValuesList();
        if(list.size() > 0) {
            for (String v : list) {
                JSONObject jsonObject = connectData.getJSONObject(v);
                String type = jsonObject.getString("type");
                if (type.equals("websocket")) {
                    String key = jsonObject.getString("url") + "_" + jsonObject.getString("deviceId");
                    if (this.sf.wcs.containsKey(key)) {
                        this.sf.wcs.get(key).close();
                        this.sf.wcs.remove(key);
                    }
                }
                if (type.equals("com")) {
                    JSONObject com = jsonObject.getJSONObject("com");
                    String key = com.getString("value");
                    if (this.sf.ccs.containsKey(key)) {
                        this.sf.ccs.get(key).close();
                        this.sf.ccs.remove(key);
                    }
                }
            }
            JOptionPane.showMessageDialog(this.getRootPane(), "操作成功");
        }else{
            JOptionPane.showMessageDialog(this.getRootPane(), "请选取要断开的连接");
        }
    }//GEN-LAST:event_jb_diconnect_selectedActionPerformed

    private void jl_connectionsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jl_connectionsMouseClicked
        if(evt.getClickCount() == 2){
            String v = this.jl_connections.getSelectedValue();
            if(v != null) {
                String msg = "此连接未连接到服务端。";
                JSONObject jsonObject = connectData.getJSONObject(v);
                String type = jsonObject.getString("type");
                if (type.equals("websocket")) {
                    String key = jsonObject.getString("url") + "_" + jsonObject.getString("deviceId");
                    if (this.sf.wcs.containsKey(key)) {
                        msg = "此连接为WebSocket连接，已连接到服务端。";
                    }
                }
                if (type.equals("com")) {
                    JSONObject com = jsonObject.getJSONObject("com");
                    if (this.sf.ccs.containsKey(com.getString("value"))) {
                        msg = "此连接为COM连接，已连接到服务端。";
                    }
                }
                JOptionPane.showMessageDialog(this.getRootPane(), msg);
            }
        }
    }//GEN-LAST:event_jl_connectionsMouseClicked

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JButton jb_add;
    private javax.swing.JButton jb_del;
    private javax.swing.JButton jb_diconnectAll;
    private javax.swing.JButton jb_diconnect_selected;
    private javax.swing.JButton jb_export;
    private javax.swing.JButton jb_load;
    private javax.swing.JButton jb_toCurrent;
    private javax.swing.JList<String> jl_connections;
    // End of variables declaration//GEN-END:variables
}
